package tbdp.tas.util.db;

import java.util.concurrent.Callable;

public final class RetryUtil {

    public static <T> T executeWithRetry(Callable<T> callable, int retryTimes,
                                         long sleepTimeInMilliSecond, boolean exponential) throws Exception {
        if (null == callable) {
            throw new IllegalArgumentException("CALLABLE NOT NULL ! ");
        }

        if (retryTimes < 1) {
            throw new IllegalArgumentException(String.format(
                    "retrytime LESS THAN 1 !", retryTimes));
        }

        Exception saveException = null;
        for (int i = 0; i < retryTimes; i++) {
            try {
                return callable.call();
            } catch (Exception e) {
                saveException = e;
                if (i + 1 < retryTimes) {
                    if (sleepTimeInMilliSecond <= 0) {
                        continue;
                    } else {
                        long timeToSleep = 0;
                        if (exponential) {
                            timeToSleep = sleepTimeInMilliSecond
                                    * (long) Math.pow(2, i);
                        } else {
                            timeToSleep = sleepTimeInMilliSecond;
                        }
                        try {
                            Thread.sleep(timeToSleep);
                        } catch (InterruptedException unused) {
                        }
                    }
                }
            }
        }

        if (saveException == null) {
            // 理论上是不会到这里的
            throw DBException.asDBException(DBErrorCode.RETRY_FAIL,
                    "MAX LIMIT EXECCED STOP  .");
        }

        throw saveException;
    }
}
